From 17aa0ca76e6eeb72da909e5a63f1367596edc536 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Fri, 31 Mar 2017 17:31:20 +0200 Subject: [PATCH] gtkwindow: Add management functions for GtkPointerFocus instances Each toplevel will keep its own tracking of the current ongoing foci, add the plumbing that will allow to create/update/remove those as they come and go. --- gtk/gtkwindow.c | 122 +++++++++++++++++++++++++++++++++++++++++ gtk/gtkwindowprivate.h | 15 +++++ 2 files changed, 137 insertions(+) diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 813a79710e..7e878897e0 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -68,6 +68,7 @@ #include "inspector/init.h" #include "inspector/window.h" #include "gtkcssstylepropertyprivate.h" +#include "gtkpointerfocusprivate.h" #include "gdk/gdk-private.h" @@ -273,6 +274,8 @@ struct _GtkWindowPrivate GtkCssNode *decoration_node; GskRenderer *renderer; + + GList *foci; }; static const GtkTargetEntry dnd_dest_targets [] = { @@ -1626,12 +1629,38 @@ node_style_changed_cb (GtkCssNode *node, gtk_widget_queue_draw (widget); } +static void +device_removed_cb (GdkSeat *seat, + GdkDevice *device, + gpointer user_data) +{ + GtkWindow *window = user_data; + GList *l = window->priv->foci, *cur; + + while (l) + { + GtkPointerFocus *focus = l->data; + + cur = l; + focus = cur->data; + l = cur->next; + + if (focus->device == device) + { + gtk_pointer_focus_free (focus); + window->priv->foci = + g_list_delete_link (window->priv->foci, cur); + } + } +} + static void gtk_window_init (GtkWindow *window) { GtkWindowPrivate *priv; GtkWidget *widget; GtkCssNode *widget_node; + GdkSeat *seat; widget = GTK_WIDGET (window); @@ -1697,6 +1726,10 @@ gtk_window_init (GtkWindow *window) GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP, dnd_dest_targets, G_N_ELEMENTS (dnd_dest_targets), GDK_ACTION_MOVE); + + seat = gdk_display_get_default_seat (gtk_widget_get_display (widget)); + g_signal_connect (seat, "device-removed", + G_CALLBACK (device_removed_cb), window); } static void @@ -11334,3 +11367,92 @@ gtk_window_get_renderer (GtkWindow *window) return priv->renderer; } + +static void +gtk_window_add_pointer_focus (GtkWindow *window, + GtkPointerFocus *focus) +{ + GtkWindowPrivate *priv = window->priv; + + priv->foci = g_list_prepend (priv->foci, focus); +} + +static void +gtk_window_remove_pointer_focus (GtkWindow *window, + GtkPointerFocus *focus) +{ + GtkWindowPrivate *priv = window->priv; + + priv->foci = g_list_remove (priv->foci, focus); +} + +static GtkPointerFocus * +gtk_window_lookup_pointer_focus (GtkWindow *window, + GdkDevice *device, + GdkEventSequence *sequence) +{ + GList *l; + + for (l = window->priv->foci; l; l = l->next) + { + GtkPointerFocus *focus = l->data; + + if (focus->device == device && focus->sequence == sequence) + return focus; + } + + return NULL; +} + +GtkWidget * +gtk_window_lookup_pointer_focus_widget (GtkWindow *window, + GdkDevice *device, + GdkEventSequence *sequence) +{ + GtkPointerFocus *focus; + + focus = gtk_window_lookup_pointer_focus (window, device, sequence); + return focus ? gtk_pointer_focus_get_target (focus) : NULL; +} + +GtkWidget * +gtk_window_lookup_effective_pointer_focus_widget (GtkWindow *window, + GdkDevice *device, + GdkEventSequence *sequence) +{ + GtkPointerFocus *focus; + + focus = gtk_window_lookup_pointer_focus (window, device, sequence); + return focus ? gtk_pointer_focus_get_effective_target (focus) : NULL; +} + +void +gtk_window_update_pointer_focus (GtkWindow *window, + GdkDevice *device, + GdkEventSequence *sequence, + GtkWidget *target, + gdouble x, + gdouble y) +{ + GtkPointerFocus *focus; + + focus = gtk_window_lookup_pointer_focus (window, device, sequence); + if (focus) + { + if (target) + { + gtk_pointer_focus_set_target (focus, target); + gtk_pointer_focus_set_coordinates (focus, x, y); + } + else + { + gtk_window_remove_pointer_focus (window, focus); + gtk_pointer_focus_free (focus); + } + } + else if (target) + { + focus = gtk_pointer_focus_new (window, target, device, sequence, x, y); + gtk_window_add_pointer_focus (window, focus); + } +} diff --git a/gtk/gtkwindowprivate.h b/gtk/gtkwindowprivate.h index 604c2973ea..b8485c72aa 100644 --- a/gtk/gtkwindowprivate.h +++ b/gtk/gtkwindowprivate.h @@ -22,6 +22,7 @@ #include #include "gtkwindow.h" +#include "gtkpointerfocusprivate.h" G_BEGIN_DECLS @@ -139,6 +140,20 @@ void gtk_window_unexport_handle (GtkWindow *window); GskRenderer *gtk_window_get_renderer (GtkWindow *window); +GtkWidget * gtk_window_lookup_pointer_focus_widget (GtkWindow *window, + GdkDevice *device, + GdkEventSequence *sequence); +GtkWidget * gtk_window_lookup_effective_pointer_focus_widget (GtkWindow *window, + GdkDevice *device, + GdkEventSequence *sequence); + +void gtk_window_update_pointer_focus (GtkWindow *window, + GdkDevice *device, + GdkEventSequence *sequence, + GtkWidget *target, + gdouble x, + gdouble y); + G_END_DECLS #endif /* __GTK_WINDOW_PRIVATE_H__ */ -- 2.30.2